﻿using System;
using System.Collections.Generic;
using System.Threading;

namespace lite.sqlserver
{
    public class CriticalDictionary<T>
    {
        /// <summary>
        /// 较好性能的锁
        /// </summary>
        private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
        /// <summary>
        /// 内部字典
        /// </summary>
        private IDictionary<string, T> _innerDictionary;
        /// <summary>
        /// 最大容量
        /// </summary>
        private int _capacity;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="capacity">最大容量</param>
        public CriticalDictionary(int capacity)
        {
            this.Capacity = capacity;
            this._innerDictionary = new Dictionary<string, T>(this._capacity);
        }

        /// <summary>
        /// 最大容量
        /// </summary>
        public int Capacity
        {
            get
            {
                return this._capacity;
            }
            set
            {
                //最小只能是10
                this._capacity = value < 10 ? 10 : value;
            }
        }

        public void Put(string key, T item)
        {
            this._lock.EnterWriteLock();
            try
            {
                //超出容量，移除第一个。
                if (this._innerDictionary.Count == this._capacity)
                {
                    foreach (var firstKey in this._innerDictionary.Keys)
                    {
                        this._innerDictionary.Remove(firstKey);
                        return;
                    }
                }
                this._innerDictionary[key] = item;
            }
            finally
            {
                this._lock.ExitWriteLock();
            }
        }

        public T Get(string key)
        {
            this._lock.EnterReadLock();
            try
            {
                T result;
                if (this._innerDictionary.TryGetValue(key, out result))
                {
                    return result;
                }
                return default(T);
            }
            finally
            {
                this._lock.ExitReadLock();
            }
        }
    }
}
